home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright 1990,1991,1992,1994 Eric R. Smith.
- All rights reserved.
- */
-
- /* dossig.c:: dos signal handling routines */
-
- #include "mint.h"
-
- void ARGS_ON_STACK sig_user P_((int vec));
-
- /*
- * send a signal to another process. If pid > 0, send the signal just to
- * that process. If pid < 0, send the signal to all processes whose process
- * group is -pid. If pid == 0, send the signal to all processes with the
- * same process group id.
- *
- * note: post_sig just posts the signal to the process.
- */
-
- long ARGS_ON_STACK
- p_kill(pid, sig)
- int pid, sig;
- {
- PROC *p;
- long r;
-
- TRACE(("Pkill(%d, %d)", pid, sig));
- if (sig < 0 || sig >= NSIG) {
- DEBUG(("Pkill: signal out of range"));
- return ERANGE;
- }
-
- if (pid < 0)
- r = killgroup(-pid, sig, 0);
- else if (pid == 0)
- r = killgroup(curproc->pgrp, sig, 0);
- else {
- p = pid2proc(pid);
- if (p == 0 || p->wait_q == ZOMBIE_Q || p->wait_q == TSR_Q) {
- DEBUG(("Pkill: pid %d not found", pid));
- return EFILNF;
- }
- if (curproc->euid && curproc->ruid != p->ruid) {
- DEBUG(("Pkill: wrong user"));
- return EACCDN;
- }
-
- /* if the user sends signal 0, don't deliver it -- for users, signal
- * 0 is a null signal used to test the existence of a process
- */
- if (sig != 0)
- post_sig(p, sig);
- r = 0;
- }
-
- if (r == 0) {
- check_sigs();
- TRACE(("Pkill: returning OK"));
- }
- return r;
- }
-
- /*
- * set a user-specified signal handler, POSIX.1 style
- * "oact", if non-null, gets the old signal handling
- * behaviour; "act", if non-null, specifies new
- * behaviour
- */
-
- long ARGS_ON_STACK
- p_sigaction(sig, act, oact)
- int sig;
- const struct sigaction *act;
- struct sigaction *oact;
- {
- TRACE(("Psigaction(%d)", sig));
- if (sig < 1 || sig >= NSIG)
- return ERANGE;
- if (act && (sig == SIGKILL || sig == SIGSTOP))
- return EACCDN;
- if (oact) {
- oact->sa_handler = curproc->sighandle[sig];
- oact->sa_mask = curproc->sigextra[sig];
- oact->sa_flags = curproc->sigflags[sig] & SAUSER;
- }
- if (act) {
- ushort flags;
-
- curproc->sighandle[sig] = act->sa_handler;
- curproc->sigextra[sig] = act->sa_mask & ~UNMASKABLE;
-
- /* only the flags in SAUSER can be changed by the user */
- flags = curproc->sigflags[sig] & ~SAUSER;
- flags |= act->sa_flags & SAUSER;
- curproc->sigflags[sig] = flags;
-
- /* various special things that should happen */
- if (act->sa_handler == SIG_IGN) {
- /* discard pending signals */
- curproc->sigpending &= ~(1L<<sig);
- }
-
- /* I dunno if this is right, but bash seems to expect it */
- curproc->sigmask &= ~(1L<<sig);
- }
- return 0;
- }
-
- /*
- * set a user-specified signal handler
- */
-
- long ARGS_ON_STACK
- p_signal(sig, handler)
- int sig;
- long handler;
- {
- long oldhandle;
-
- TRACE(("Psignal(%d, %lx)", sig, handler));
- if (sig < 1 || sig >= NSIG)
- return ERANGE;
- if (sig == SIGKILL || sig == SIGSTOP)
- return EACCDN;
- oldhandle = curproc->sighandle[sig];
- curproc->sighandle[sig] = handler;
- curproc->sigextra[sig] = 0;
- curproc->sigflags[sig] = 0;
-
- /* various special things that should happen */
- if (handler == SIG_IGN) {
- /* discard pending signals */
- curproc->sigpending &= ~(1L<<sig);
- }
-
- /* I dunno if this is right, but bash seems to expect it */
- curproc->sigmask &= ~(1L<<sig);
-
- return oldhandle;
- }
-
- /*
- * block some signals. Returns the old signal mask.
- */
-
- long ARGS_ON_STACK
- p_sigblock(mask)
- ulong mask;
- {
- ulong oldmask;
-
- TRACE(("Psigblock(%lx)",mask));
- /* some signals (e.g. SIGKILL) can't be masked */
- mask &= ~(UNMASKABLE);
- oldmask = curproc->sigmask;
- curproc->sigmask |= mask;
- return oldmask;
- }
-
- /*
- * set the signals that we're blocking. Some signals (e.g. SIGKILL)
- * can't be masked.
- * Returns the old mask.
- */
-
- long ARGS_ON_STACK
- p_sigsetmask(mask)
- ulong mask;
- {
- ulong oldmask;
-
- TRACE(("Psigsetmask(%lx)",mask));
- oldmask = curproc->sigmask;
- curproc->sigmask = mask & ~(UNMASKABLE);
- check_sigs(); /* maybe we unmasked something */
- return oldmask;
- }
-
- /*
- * p_sigpending: return which signals are pending delivery
- */
-
- long ARGS_ON_STACK
- p_sigpending()
- {
- TRACE(("Psigpending()"));
- check_sigs(); /* clear out any that are going to be delivered soon */
-
- /* note that signal #0 is used internally, so we don't tell the process
- * about it
- */
- return curproc->sigpending & ~1L;
- }
-
- /*
- * p_sigpause: atomically set the signals that we're blocking, then pause.
- * Some signals (e.g. SIGKILL) can't be masked.
- */
-
- long ARGS_ON_STACK
- p_sigpause(mask)
- ulong mask;
- {
- ulong oldmask;
-
- TRACE(("Psigpause(%lx)", mask));
- oldmask = curproc->sigmask;
- curproc->sigmask = mask & ~(UNMASKABLE);
- if (curproc->sigpending & ~(curproc->sigmask))
- check_sigs(); /* a signal is immediately pending */
- else
- sleep(IO_Q, -1L);
- curproc->sigmask = oldmask;
- check_sigs(); /* maybe we unmasked something */
- TRACE(("Psigpause: returning OK"));
- return 0;
- }
-
- /*
- * p_sigintr: Set an exception vector to send us the specified signal.
- */
-
- typedef struct usig {
- int vec; /* exception vector number */
- int sig; /* signal to send */
- PROC *proc; /* process to get signal */
- long oldv; /* old exception vector value */
- struct usig *next; /* next entry ... */
- } usig;
-
- static usig *usiglst;
- extern long mcpu;
-
- long ARGS_ON_STACK
- p_sigintr(vec, sig)
- int vec;
- int sig;
- {
- extern void new_intr(); /* in intr.spp */
- long vec2;
- usig *new;
-
- if (!sig) /* ignore signal 0 */
- return 0;
-
- vec2 = (long) new_intr;
-
- #ifndef ONLY030
- if (mcpu == 0)
- /* put vector number in high byte of vector address */
- vec2 |= ((long) vec) << 24;
- #endif
- new = kmalloc(sizeof(usig));
- if (!new) /* hope this never happens...! */
- return ENSMEM;
- new->vec = vec;
- new->sig = sig;
- new->proc = curproc;
- new->next = usiglst; /* simple unsorted list... */
- usiglst = new;
-
- new->oldv = setexc(vec, vec2);
- return new->oldv;
- }
-
- /*
- * Find the process that requested this interrupt, and send it a signal.
- * Called at interrupt time by new_intr() from intr.spp, with interrupt
- * vector number on the stack.
- */
-
- void ARGS_ON_STACK
- sig_user(vec)
- int vec;
- {
- usig *ptr;
-
- for (ptr = usiglst; ptr; ptr=ptr->next)
- if (vec == ptr->vec) {
- if (ptr->proc->wait_q != ZOMBIE_Q &&
- ptr->proc->wait_q != TSR_Q) {
- post_sig(ptr->proc, ptr->sig);
- }
- #if 0 /* Search entire list, to allow multiple processes to respond to
- the same interrupt. (Why/when would you want that?) */
- break;
- #endif
- }
- /*
- * Clear in-service bit for ST MFP interrupts
- */
- if (vec >= 64 && vec < 80) {
- char *mfp, c;
-
- if (vec < 72) /* Register B */
- mfp = (char *)0xfffffa11L;
- else /* Register A */
- mfp = (char *)0xfffffa0fL;
- c = 1 << (vec & 7);
-
- *mfp = ~c;
- }
- }
-
- /*
- * cancelsigintrs: remove any interrupts requested by this process, called
- * at process termination.
- */
- void
- cancelsigintrs()
- {
- usig *ptr, **old, *nxt;
- short s = spl7();
-
- for (old=&usiglst, ptr=usiglst; ptr; ) {
- nxt = ptr->next;
- if (ptr->proc == curproc) {
- setexc(ptr->vec, ptr->oldv);
- *old = nxt;
- kfree(ptr);
- } else {
- old = &(ptr->next);
- }
- ptr = nxt;
- }
- spl(s);
- }
-